package krypto.exercise;

import java.math.BigInteger;

public class W2e7 {
	public static void main(String[] args) {
		BigInteger r = BigInteger.valueOf(0b100011011);
		int l = 8;

		r = BigInteger.valueOf(0b1101);
		l = 3;
		
		int n = (int) Math.pow(2, (double)l); //looks ugly, but works

		int counter = 0;
		int hitCounter = 0;
		String s;

		//Do exhaustive search
		for (int aa = 0; aa < n  ; aa++) {
			for (int bb = 0; bb < n  ; bb++) {
//				System.out.println("Result of GFAdd(" + Integer.toBinaryString(aa) + "," + Integer.toBinaryString(bb) + ") = " + GFAdd(BigInteger.valueOf(aa),BigInteger.valueOf(bb)).toString(2) + " ");

				s = GFMul(BigInteger.valueOf(aa),BigInteger.valueOf(bb),r,l).toString(2);
				System.out.println("Result of GFMul(" + Integer.toBinaryString(aa) + "," + Integer.toBinaryString(bb) + ") = " + s);
				
				if (s.equalsIgnoreCase("1")) {
//					System.out.println("Result of GFMul(" + Integer.toBinaryString(aa) + "," + Integer.toBinaryString(bb) + ") = " + s);
//					
					hitCounter++;
				}
				
				counter++;
			}
		}
		
		System.out.println("Counter = " + counter + " HitCounter = " + hitCounter);
	}


	private static BigInteger GFMul(BigInteger a, BigInteger b, BigInteger r, int l) {
		BigInteger temp;
		BigInteger result = BigInteger.valueOf(0);

		//This is described in part 1 of the exercise
		for (int i=0; i<=b.toString(2).length(); i++) {
			if (b.testBit(i)) { 
				temp = a.shiftLeft(i); 
				result = result.xor(temp);
			}
		}

		//This is described in part 2 of the exercise
		// if result need to be reduced further we do it
		while (result.toString(2).length() > l) {
			BigInteger rtemp = r;

			while (result.toString(2).length() != rtemp.toString(2).length()) {
				rtemp = rtemp.shiftLeft(1);
			}
			
			result = result.xor(rtemp);
		}

		return result;
	}

	@SuppressWarnings("unused")
	//Not actually used, but kept just in case I need to do to addition later on. 
	private static BigInteger GFAdd(BigInteger a, BigInteger b) {
		return a.xor(b);
	}

}
